package com.imyuanma.qingyun.common.config.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;

/**
 * Spring Security 配置
 *
 * @author wangjy
 * @date 2022/07/09 15:17:45
 */
@Configuration
@EnableWebSecurity
public class QingYunSecurityConfig extends WebSecurityConfigurerAdapter {
    private static final Logger logger = LoggerFactory.getLogger(QingYunSecurityConfig.class);

    @Autowired
    private QingYunSecurityConfiguration securityConfiguration;

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private DefaultLoginSuccessHandler defaultLoginSuccessHandler;
    @Autowired
    private DefaultLoginFailureHandler defaultLoginFailureHandler;
    @Autowired
    private DefaultSessionAuthFailureHandler defaultSessionAuthFailureHandler;
    @Autowired
    private DefaultInvalidSessionStrategy defaultInvalidSessionStrategy;
    @Autowired
    private DefaultSecurityContextRepository defaultSecurityContextRepository;
    @Autowired
    private DefaultAuthenticationEntryPoint defaultAuthenticationEntryPoint;
    @Autowired
    private DefaultAccessDeniedHandler defaultAccessDeniedHandler;
    @Autowired
    private DefaultLogoutSuccessHandler defaultLogoutSuccessHandler;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(DefaultPasswordEncoder.newInstance("qingyun"));
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 不设置默认会返回响应头 X-Frame-Options: DENY, 表示拒绝加载iframe
        http.headers().frameOptions().disable();
        // 关闭csrf校验, 否则post请求会返回403
        http.csrf().disable();
        http.authorizeRequests()
                // 不需要强登录的请求
                .antMatchers(securityConfiguration.getSsoWhite()).permitAll()
                // 拦截的请求
                .anyRequest().authenticated();
        logger.info("[轻云SpringSecurity配置] 非强登录的链接为:{}", securityConfiguration.getSsoWhite());

        // 登录配置
        http.formLogin()
                .usernameParameter("account")
                .passwordParameter("password")
                .loginPage("/page/login.html")
                .loginProcessingUrl("/sso/login")
//                .defaultSuccessUrl("/")
                .successHandler(defaultLoginSuccessHandler)
                .failureHandler(defaultLoginFailureHandler)
                .permitAll();
//                .and().rememberMe()

        // 注销登录配置
        http.logout()
                .logoutUrl("/sso/logout")
                .logoutSuccessUrl("/page/login.html")
                .logoutSuccessHandler(defaultLogoutSuccessHandler)
                .permitAll();

        // 会话管理
        http.sessionManagement().disable();

        // 上下文资源库
        http.securityContext().securityContextRepository(defaultSecurityContextRepository);

        http.exceptionHandling()
                // 认证失败处理, 未登录访问需认证资源时触发
                .authenticationEntryPoint(defaultAuthenticationEntryPoint)
                // 访问拒绝处理, 无权限时触发
                .accessDeniedHandler(defaultAccessDeniedHandler);

    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // 配置静态文件不需要认证
        web.ignoring().antMatchers(securityConfiguration.getIgnoreWhite());
    }
}
